﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EBA.IoC
{
    public class LifetimeManager : ILifetimeManager
    {
        Dictionary<ObjectLiveKey, object> _Instances = new Dictionary<ObjectLiveKey, object>();
        Dictionary<ObjectLiveKey, Func<string, object>> _Factories = new Dictionary<ObjectLiveKey, Func<string, object>>();


        public object GetInstance(Type hostType, Type instanceType)
        {
            return this.GetInstance(hostType, instanceType, null);
        }

        public object GetInstance(Type hostType, Type instanceType, string contractName)
        {
            var key = this.BuildLiveKey(hostType, instanceType, contractName);

            object instance;
            if(this._Instances.TryGetValue(key,out instance)){
                return instance;
            }

            Func<string, object> factory;
            if (this._Factories.TryGetValue(key, out factory))
            {
                return factory(contractName);
            }

            return null;
        }

        public void RegisterInstance(Type hostType, Type instanceType, object instance)
        {
            this.RegisterInstance(hostType, instanceType, null,instance);
        }

        public void RegisterInstance(Type hostType, Type instanceType, string contractName, object instance)
        {
            var key = this.BuildLiveKey(hostType, instanceType, contractName);
            this._Instances[key] = instance;
        }

        public void RegisterFactory<THostType, TInstanceType>(Func<object> factory)
        {
            Func<string, object> item = i => factory();
            this.RegisterFactory<THostType, TInstanceType>(null, item);
        }

        public void RegisterFactory<THostType, TInstanceType>(string contractName, Func<string, object> factory)
        {
            var key = this.BuildLiveKey(typeof(THostType), typeof(TInstanceType), contractName);
            this._Factories[key] = factory;
        }

        ObjectLiveKey BuildLiveKey(Type host, Type instance, string contractName)
        {
            return new ObjectLiveKey { HostType = host, InstanceType = instance, ContractName = contractName };
        }
    }
}
